package com.owen.he.jee.service.impl.excel;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import java.util.Map;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

import org.apache.log4j.helpers.LogLog;

import com.owen.he.jee.model.ExportTemplate;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

public class XMLFactory {
	
	
	private XMLFactory(){};

    private static Marshaller marshaller;
    private static Unmarshaller unmarshaller;
    
    /**
     * @param types 参数types为所有需要序列化的Root对象的类型.
     */
    public XMLFactory(Class<?>... types) {
        try {
            JAXBContext jaxbContext = JAXBContext.newInstance(types);
            marshaller = jaxbContext.createMarshaller();
            marshaller.setProperty("jaxb.formatted.output", Boolean.TRUE);
            unmarshaller = jaxbContext.createUnmarshaller();
        } catch (JAXBException e) {
            throw new RuntimeException(e);
        }
    }
    
    /**
     * Java->Xml
     * @param root 要转化的对象
     * @return
     */
    public static String marshal(Object root) {
        try {
            StringWriter writer = new StringWriter();
            marshaller.marshal(root, writer);
            return writer.toString();
        } catch (JAXBException e) {
            throw new RuntimeException(e);
        }
    }
    
    /**
     * Xml->Java
     * @param xml xml字符串
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T unmarshal(String xml) {
        try {
            StringReader reader = new StringReader(xml);
            return (T) unmarshaller.unmarshal(reader);
        } catch (JAXBException e) {
            throw new RuntimeException(e);
        }
    }
    
    /**
     * Xml->Java
     * @param in xml文件流
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T unmarshal(InputStream in) {
        BufferedReader br = null;
        try {
            br = new BufferedReader(new InputStreamReader(in, "utf-8"));
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
        try {
            return (T) unmarshaller.unmarshal(br);
        } catch (JAXBException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     *  将传入xml文本转换成Java对象
     * @Title: toBean 
     * @Description: TODO 
     * @param xmlStr
     * @param cls  xml对应的class类
     * @return T   xml对应的class类的实例对象
     * 调用的方法实例：PersonBean person=XmlUtil.toBean(xmlStr, PersonBean.class);
     */
    public static <T> T  xmlStrToBean(String xmlStr,Class<T> cls){
        //注意：不是new Xstream(); 否则报错：java.lang.NoClassDefFoundError: org/xmlpull/v1/XmlPullParserFactory
        XStream xstream=new XStream(new DomDriver());
        xstream.processAnnotations(cls);
        T obj=(T)xstream.fromXML(xmlStr);
        return obj;         
    }
    
    /** 
     * 将Bean转换为字符串 XML 
     * @param clazzMap 别名-类名映射Map 
     * @param bean     要转换为xml的bean对象 
     * @return XML字符串 
     */ 
    public static String beanToXmlStr(Map<String, Class> clazzMap, Object bean) { 
        XStream xstream = new XStream(); 
        for (Iterator it = clazzMap.entrySet().iterator(); it.hasNext();) { 
            Map.Entry<String, Class> m = (Map.Entry<String, Class>) it.next(); 
            xstream.alias(m.getKey(), m.getValue()); 
        } 
        String xml = xstream.toXML(bean); 
        return xml; 
    } 

    /** 
     * 将字符串XML转换为Bean 
     * @param clazzMap 别名-类名映射Map 
     * @param xml      要转换为bean对象的xml字符串 
     * @return Java Bean对象 
     */ 
    public static Object xmlStrToBean(Map<String, Class> clazzMap, String xml) { 
        XStream xstream = new XStream(); 
        for (Iterator it = clazzMap.entrySet().iterator(); it.hasNext();) { 
            Map.Entry<String, Class> m = (Map.Entry<String, Class>) it.next(); 
            xstream.alias(m.getKey(), m.getValue()); 
        } 
        Object bean = xstream.fromXML(xml); 
        return bean; 
    } 

    /** 
     * 获取XStream对象 
     * @param clazzMap 别名-类名映射Map 
     * @return XStream对象 
     */ 
    public static XStream getXStreamObject(Map<String, Class> clazzMap) { 
        XStream xstream = new XStream(); 
        for (Iterator it = clazzMap.entrySet().iterator(); it.hasNext();) { 
            Map.Entry<String, Class> m = (Map.Entry<String, Class>) it.next(); 
            xstream.alias(m.getKey(), m.getValue()); 
        } 
        return xstream; 
    }
    
    /**
     * java 转换成xml
     * @Title: toXml 
     * @Description: TODO 
     * @param obj 对象实例
     * @return String xml字符串
     */
    public static String beanToXmlStr(Object obj){
        XStream xstream=new XStream();
        //XStream xstream=new XStream(new DomDriver()); //直接用jaxp dom来解释
        //XStream xstream=new XStream(new DomDriver("utf-8")); //指定编码解析器,直接用jaxp dom来解释
        ////如果没有这句，xml中的根元素会是<包.类名>；或者说：注解根本就没生效，所以的元素名就是类的属性
        xstream.processAnnotations(obj.getClass()); //通过注解方式的，一定要有这句话
        return xstream.toXML(obj);
    }

    /**
     * 从xml文件读取报文
     * @Title: toBeanFromFile 
     * @Description: TODO 
     * @param absPath 绝对路径
     * @param fileName 文件名
     * @param cls
     * @throws Exception 
     * @return T
     */
    public static <T> T  xmlFileToBean(String filePath, Class<T> cls) throws Exception{
        InputStream ins = null ;
        try {
        	File file = new File(filePath);
			if (!file.exists()) {
				throw new Exception("{"+ filePath +"}文件不存在！");
			}
            ins = new FileInputStream(file);
        } catch (Exception e) {
            throw new Exception("读{"+ filePath +"}文件失败！", e);
        }
        T obj =null;
        try {
            obj = unmarshal(ins);
        } catch (Exception e) {
            throw new Exception("解析{"+ filePath +"}文件失败！",e);
        }
        if(ins != null)
            ins.close();
        return obj;         
    } 
    
   /**
     * 写到xml文件中去
     * @Title: writeXMLFile 
     * @Description: TODO 
     * @param obj 对象
     * @param absPath 绝对路径
     * @param fileName  文件名
     * @return boolean
     */
   
    public static boolean beanToXmlFile(Object obj, String absPath, String fileName ){
        String strXml = beanToXmlStr(obj);
        String filePath = absPath + fileName;
        File file = new File(filePath);
        if(!file.exists()){
            try {
                file.createNewFile();
            } catch (IOException e) {
            	LogLog.error("创建{"+ filePath +"}文件失败!!!" + e.getMessage());
                return false ;
            }
        }// end if 
        OutputStream ous = null ;
        try {
            ous = new FileOutputStream(file);
            ous.write(strXml.getBytes());
            ous.flush();
        } catch (Exception e1) {
        	LogLog.error("写{"+ filePath +"}文件失败!!!" + e1.getMessage());
            return false;
        }finally{
            if(ous != null )
                try {
                    ous.close();
                } catch (IOException e) {
                	LogLog.error("写{"+ filePath +"}文件关闭输出流异常!!!" + e.getMessage());
                }
        }
        return true ;
    }
    
    public static void main(String[] args) {
    	ExportTemplate f = new ExportTemplate();
    	f.setBarName("业绩关系");
    	XMLFactory fact = new XMLFactory(ExportTemplate.class);
    	String s = fact.marshal(f);
    	System.out.println(s);
	}
    
}